package com.yanqu.road.server.channelserver.manager.activity.washe.game;

import com.yanqu.road.entity.activity.washe.config.WasheConfig;
import com.yanqu.road.entity.activity.washe.config.WasheHardLevelConfig;
import com.yanqu.road.entity.activity.washe.data.WasheUserMatchData;
import com.yanqu.road.entity.activity.washe.eliminate.WasheAiMoveParam;
import com.yanqu.road.entity.activity.washe.eliminate.WasheBlock;
import com.yanqu.road.entity.activity.washe.eliminate.WasheGameData;
import com.yanqu.road.entity.activity.washe.eliminate.WasheMoveParam;
import com.yanqu.road.entity.activity.washe.eliminate.WasheUseSkillParam;
import com.yanqu.road.entity.activity.washe.game.WasheRoomData;
import com.yanqu.road.entity.activity.washe.game.WasheUserGameCard;
import com.yanqu.road.entity.activity.washe.game.WasheUserGameData;
import com.yanqu.road.entity.activity.washe.game.WasheUserGameSkill;
import com.yanqu.road.entity.enums.washe.*;
import com.yanqu.road.server.channelserver.manager.activity.washe.ChannelWasheActivity;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.RandomHelper;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;

/**
 * 整个类都很傻逼
 */
public class WasheAiLogic {

    public static int aiOperate(ChannelWasheActivity activity, WasheConfig config, WasheRoomData roomData, WasheUserMatchData realPlayer, WasheUserGameData aiPlayer) {

        // 拿AI难度
        // 巅峰赛取最大段位id
        int hardLevel;
        if (roomData.getModeId() == eWasheModeType.JinBiaoPeak.getValue()) {
            hardLevel = config.getJinBiaoPeakAILevel();
        } else {
            List<Integer> hardWeightList = config.getAiHardList().get(0);
            int rankId = config.getWasheRankConfig(realPlayer.getScore(), realPlayer.isNewHand()).getRankId();
            for (List<Integer> list : config.getAiHardList()) {
                if (list.get(0) <= rankId && rankId <= list.get(1)) {
                    hardWeightList = new ArrayList<>(list);
                    hardWeightList.remove(0);
                    hardWeightList.remove(0);
                }
            }
            hardLevel = RandomHelper.getRandomIndexByWeight(hardWeightList) + 1;
        }
        WasheHardLevelConfig hardLevelConfig = config.getHardLevelConfigMap().get(hardLevel);

        // -------------------- 准备结果 -----------------------

        boolean canUseCard = false;
        WasheUserGameCard card = aiPlayer.getCard();
        if (card.getCardMp() >= card.getCardMaxMp()) {
            canUseCard = true;
        }

        int side = roomData.getPlayer1() == aiPlayer ? 1 : 2;
        WasheAiMoveParam bestAiMove = getBestAiMove(roomData.getGameData(), side, aiPlayer, hardLevelConfig);

        // -------------------- 选一种好用的操作 -----------------------

        if (bestAiMove == null) {
            return GameErrorCode.E_WASHE_PARAM_ERROR;
        }

        // 默认移动
        eWasheOperateType operateType = eWasheOperateType.Move;
        int weight = bestAiMove.getWeight(hardLevelConfig);

        // 看看卡片
        if (canUseCard && hardLevelConfig.getCardWeight() > weight) {
            operateType = eWasheOperateType.UseCard;
            weight = hardLevelConfig.getCardWeight();
        }

        // 看看盘面技能
        int useSkillId = 0;
        int skillX = 0;
        int skillY = 0;
        if (weight < hardLevelConfig.getSkillWeight() || roomData.getRound() >= 5) { // 有权重限制 || 第五回合强制判断
            for (WasheUserGameSkill skill : aiPlayer.getSkillList()) {

                if (skill.getSkillId() == eWasheSkillType.Skill_1001.getValue()) {
                    // 有次数 && 第2回合及以后 && 50%概率触发
                    if (skill.getTimes() > 0 && roomData.getRound() >= 2 && new Random().nextInt(1000) < 500) {
                        weight = hardLevelConfig.getSkillWeight();
                        operateType = eWasheOperateType.UseSkill;
                        useSkillId = skill.getSkillId();
                        break;
                    }
                }

                if (skill.getSkillId() == eWasheSkillType.Skill_1002.getValue()) {
                    // 有次数 && 第3回合及以后 && 排序后选最优的
                    if (skill.getTimes() > 0 && roomData.getRound() >= 3) {
                        List<WasheBlock> all = new ArrayList<>();
                        for (List<WasheBlock> blockList : roomData.getGameData().getBlockList()) {
                            all.addAll(blockList);
                        }
                        int mpColor = roomData.getTurnPlayer() == 1 ? eWasheColorType.Red.getValue() : eWasheColorType.Blue.getValue();
                        all.sort(new Comparator<WasheBlock>() {
                            @Override
                            public int compare(WasheBlock o1, WasheBlock o2) {
                                return Integer.compare(
                                        getBlockSortScore(o2, mpColor),
                                        getBlockSortScore(o1, mpColor)
                                );
                            }
                        });
                        WasheBlock chooseBlock = all.get(0);
                        int sortScore = getBlockSortScore(chooseBlock, mpColor);
                        // 是炸弹 || 操作后满蓝
                        if (sortScore > 1000 || sortScore > 100 && aiPlayer.getCard().getCardMp() + 1 == aiPlayer.getCard().getCardMaxMp()) {
                            weight = hardLevelConfig.getSkillWeight();
                            operateType = eWasheOperateType.UseSkill;
                            useSkillId = skill.getSkillId();
                            skillX = chooseBlock.getX();
                            skillY = chooseBlock.getY();
                            break;
                        }
                    }
                }
            }
        }

        // --------------------- 执行操作 ----------------------

        // 【使用盘面技能】
        if (operateType == eWasheOperateType.UseSkill) {
            WasheUseSkillParam skillParam = new WasheUseSkillParam();
            skillParam.setSkillId(useSkillId);
            skillParam.setX(skillX);
            skillParam.setY(skillY);
            return activity.operateNpcUseSkill(roomData, skillParam, aiPlayer);
        }

        // 【使用卡片】
        if (operateType == eWasheOperateType.UseCard) {
            WasheUseSkillParam skillParam = new WasheUseSkillParam();
            skillParam.setSkillId(card.getCardId());
            // 暂时只能操作无参数卡片
            return activity.operateNpcUseCard(roomData, skillParam, aiPlayer);
        }

        // 【移动】
        return activity.operateNpcMove(roomData, bestAiMove.getMoveParam(), aiPlayer);
    }

    /**
     * userGameData 可以null
     */
    public static WasheAiMoveParam getBestAiMove(WasheGameData gameData, int side, WasheUserGameData userGameData, WasheHardLevelConfig hardLevelConfig) {
        WasheAiMoveParam bestParam = null;
        List<List<WasheBlock>> blockList = gameData.clone().getBlockList();

        // 先检查组合炸弹
        for (int y = 0; y < blockList.size(); y++) {
            for (int x = 0; x < blockList.get(y).size(); x++) {
                WasheBlock from = blockList.get(y).get(x);
                if (WasheGameLogic.isCombBombPart(from)) {
                    if (WasheGameLogic.isXyExist(blockList, x + 1, y) && WasheGameLogic.isCombBombPart(blockList.get(y).get(x + 1))) {
                        WasheAiMoveParam aiMoveParam = createWasheAiMoveParam(blockList, x, y, x + 1, y, side, userGameData);
                        if (bestParam == null || aiMoveParam.getWeight(hardLevelConfig) > bestParam.getWeight(hardLevelConfig)) {
                            bestParam = aiMoveParam;
                        }
                    }
                    if (WasheGameLogic.isXyExist(blockList, x, y + 1) && WasheGameLogic.isCombBombPart(blockList.get(y + 1).get(x))) {
                        WasheAiMoveParam aiMoveParam = createWasheAiMoveParam(blockList, x, y, x, y + 1, side, userGameData);
                        if (bestParam == null || aiMoveParam.getWeight(hardLevelConfig) > bestParam.getWeight(hardLevelConfig)) {
                            bestParam = aiMoveParam;
                        }
                    }
                }
            }
        }

        // 遍历每个方块尝试交换
        for (int y = 0; y < blockList.size(); y++) {
            for (int x = 0; x < blockList.get(y).size(); x++) {

                // 跟右边交换
                int x2 = x + 1;
                int y2 = y;
                if (WasheGameLogic.isXyExist(blockList, x2, y2)) {
                    WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                    if (WasheGameLogic.canSameColorEliminate(blockList, blockList.get(y).get(x)) || WasheGameLogic.canSameColorEliminate(blockList, blockList.get(y2).get(x2))) {
                        WasheAiMoveParam aiMoveParam = createWasheAiMoveParam(blockList, x, y, x2, y2, side, userGameData);
                        if (bestParam == null || aiMoveParam.getWeight(hardLevelConfig) > bestParam.getWeight(hardLevelConfig)) {
                            bestParam = aiMoveParam;
                        }
                    }
                    WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                }

                // 跟上边交换
                x2 = x;
                y2 = y + 1;
                if (WasheGameLogic.isXyExist(blockList, x2, y2)) {
                    WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                    if (WasheGameLogic.canSameColorEliminate(blockList, blockList.get(y).get(x)) || WasheGameLogic.canSameColorEliminate(blockList, blockList.get(y2).get(x2))) {
                        WasheAiMoveParam aiMoveParam = createWasheAiMoveParam(blockList, x, y, x2, y2, side, userGameData);
                        if (bestParam == null || aiMoveParam.getWeight(hardLevelConfig) > bestParam.getWeight(hardLevelConfig)) {
                            bestParam = aiMoveParam;
                        }
                    }
                    WasheGameLogic.exchangeBlock(blockList, x, y, x2, y2, null);
                }

            }
        }

        return bestParam;
    }

    /**
     * @param userGameData 可以null
     */
    private static WasheAiMoveParam createWasheAiMoveParam(List<List<WasheBlock>> blockList, int x1, int y1, int x2, int y2, int side, WasheUserGameData userGameData) {
        WasheAiMoveParam param = new WasheAiMoveParam();
        param.setMoveParam(new WasheMoveParam(x1, y1, x2, y2));

        int blueColor = side == 1 ? eWasheColorType.Red.getValue() : eWasheColorType.Blue.getValue();
        int redColor = side == 1 ? eWasheColorType.Blue.getValue() : eWasheColorType.Red.getValue();
        int addMp = 0;

        List<WasheBlock> block12 = new ArrayList<>();
        block12.add(blockList.get(y1).get(x1));
        block12.add(blockList.get(y2).get(x2));

        for (WasheBlock block : block12) {
            int color = block.getColor();
            Set<WasheBlock> xSet = new HashSet<>();
            Set<WasheBlock> ySet = new HashSet<>();
            xSet.add(block);
            ySet.add(block);

            int tmpX = block.getX() + 1;
            int tmpY = block.getY();
            if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                xSet.add(blockList.get(tmpY).get(tmpX));
                tmpX++;
                if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                    xSet.add(blockList.get(tmpY).get(tmpX));
                }
            }
            tmpX = block.getX() - 1;
            tmpY = block.getY();
            if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                xSet.add(blockList.get(tmpY).get(tmpX));
                tmpX--;
                if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                    xSet.add(blockList.get(tmpY).get(tmpX));
                }
            }
            tmpX = block.getX();
            tmpY = block.getY() + 1;
            if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                ySet.add(blockList.get(tmpY).get(tmpX));
                tmpY++;
                if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                    ySet.add(blockList.get(tmpY).get(tmpX));
                }
            }
            tmpX = block.getX();
            tmpY = block.getY() - 1;
            if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                ySet.add(blockList.get(tmpY).get(tmpX));
                tmpY--;
                if (WasheGameLogic.isXyExist(blockList, tmpX, tmpY) && blockList.get(tmpY).get(tmpX).getColor() == color) {
                    ySet.add(blockList.get(tmpY).get(tmpX));
                }
            }

            if (xSet.size() >= 3 && ySet.size() >= 3 || xSet.size() >= 4 || ySet.size() >= 4) {
                param.setCreateBomb(true); // 【修改】
            }
            if (xSet.size() >= 3) {
                for (WasheBlock tmp : xSet) {
                    if (tmp.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB ||
                            tmp.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL_BOMB ||
                            tmp.getEffectList().size() > 0) {
                        param.setBoom(true); // 【修改】
                        break;
                    }
                }
            }
            if (ySet.size() >= 3 && !param.isBoom()) {
                for (WasheBlock tmp : ySet) {
                    if (tmp.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB ||
                            tmp.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL_BOMB ||
                            tmp.getEffectList().size() > 0) {
                        param.setBoom(true); // 【修改】
                        break;
                    }
                }
            }
            if (xSet.size() >= 3 && ySet.size() >= 3) {
                param.setDoubleEliminate(true); // 【修改】
            }
            if (block.getColor() == blueColor) {
                addMp = addMp + (xSet.size() >= 3 ? xSet.size() : 0) + (ySet.size() >= 3 ? ySet.size() : 0);
                param.setAddMp(true); // 【修改】
            }
            if (block.getColor() == redColor) {
                param.setSubMp(true); // 【修改】
            }
        }

        // 【判断组合炸弹】
        if (WasheGameLogic.isCombBombPart(block12.get(0)) && WasheGameLogic.isCombBombPart(block12.get(1))) {
            param.setCombBoom(true); // 【修改】
        }

        // 【判断蓝满了】
        if (userGameData != null) {
            WasheUserGameCard card = userGameData.getCard();
            if (userGameData.getStep() == 1 || param.isCreateBomb()) { // 还有步数
                if (addMp + card.getCardMp() >= card.getCardMaxMp()) {
                    param.setHasStepMpFull(true);
                }
            }
        }

        return param;
    }

    private static int getBlockSortScore(WasheBlock block, int mpColor) {
        int score = 0;

        // 类型
        if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_NORMAL_BOMB || block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL_BOMB) {
            score += 1000;
        } else if (block.getBlockType().getBigType() == eWasheBlockType.BIG_TYPE_SPECIAL) {
            score += 50;
        }

        // 颜色
        if (block.getColor() == mpColor) {
            score += 100;
        }

        // 位置（越下面越好）
        score += (10 - block.getY());

        return score;
    }

}
